
package com.example.lin.day9_14;

import android.graphics.Color;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.support.v4.hardware.fingerprint.FingerprintManagerCompat;
import android.support.v4.os.CancellationSignal;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 指纹识别
 *
 * @author LinHuaming
 */
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    
    /**
     * 用于显示指纹识别状态
     */
    private TextView tv_show;
    /**
     * Log 的 TAG 标记名称
     */
    private String TAG = MainActivity.class.getSimpleName();

    /**
     * 指纹验证取消信号对象 (用于控制取消指纹验证)
     */
    private CancellationSignal cancellationSignal;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        tv_show = findViewById(R.id.tv_show);
        findViewById(R.id.btn_verification).setOnClickListener(this);
        findViewById(R.id.btn_cancelVerification).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_verification:
                tv_show.setTextColor(Color.BLACK);
                tv_show.setText("开始验证指纹...");
                //获取指纹管理对象
                FingerprintManagerCompat fingerprintManagerCompat = FingerprintManagerCompat.from(this);
                if (!canUseFingerprint(fingerprintManagerCompat)) {
                    Log.d(TAG, "指纹不可用");
                    return;
                }
                Log.d(TAG, "指纹可以用");
                cancellationSignal = new CancellationSignal();
                //开始验证指纹识别
                /**
                 * @param crypto 与调用关联的对象，如果不需要则为null.
                 * @param flags 系统预留属性,此时应该为 0
                 * @param cancel 控制取消指纹信号的对象
                 * @param callback 指纹验证结果的回调函数
                 * @param handler 指纹验证结果的 Handle 对象,一般使用 callback即可,向了解关于 handler 的使用跟踪以下源码就一目了然 {@link FingerprintManager)}
                 */
                fingerprintManagerCompat.authenticate(null, 0, cancellationSignal, new FingerprintCallback(), null);
//                fingerprintManagerCompat.authenticate(new CryptoObjectHelper().buildCryptoObject(), 0, cancellationSignal, new FingerprintCallback(), null);
                break;
            case R.id.btn_cancelVerification:
                //指纹验证是否取消
                if (!cancellationSignal.isCanceled()) {
                    //取消指纹验证
                    cancellationSignal.cancel();
                }
                break;
        }
    }

    /**
     * 是否可以使用 指纹识别
     *
     * @param managerCompat 指纹识别模块管理对象(向下兼容)
     * @return 是否可用
     */
    private boolean canUseFingerprint(FingerprintManagerCompat managerCompat) {
        // 手机是否有职位识别模块
        if (!managerCompat.isHardwareDetected())
            return false;
        //是否已经录入指纹
        return managerCompat.hasEnrolledFingerprints();
    }


    private class FingerprintCallback extends FingerprintManagerCompat.AuthenticationCallback {
        /**
         * 当多次验证失败,该方法被调用,并且在将来的一段时间内不能在使用指纹验证.或 用户手动取消验证等...
         *
         * @param errMsgId  错误状态ID 可能是 {@link FingerprintManager#FINGERPRINT_ERROR_HW_UNAVAILABLE}
         *                  ,or {@link FingerprintManager#FINGERPRINT_ERROR_UNABLE_TO_PROCESS}
         *                  ,or {@link FingerprintManager#FINGERPRINT_ERROR_TIMEOUT}  验证超时
         *                  ,or {@link FingerprintManager#FINGERPRINT_ERROR_NO_SPACE}
         *                  ,or {@link FingerprintManager#FINGERPRINT_ERROR_CANCELED} 取消验证 {@link CancellationSignal#cancel()} 被调用
         *                  ,or {@link FingerprintManager#FINGERPRINT_ERROR_LOCKOUT} 多次验证失败
         *                  ,or {@link FingerprintManager#FINGERPRINT_ERROR_VENDOR}
         *                  ,or {@link FingerprintManager#FINGERPRINT_ERROR_LOCKOUT_PERMANENT}
         *                  ,or {@link FingerprintManager#FINGERPRINT_ERROR_USER_CANCELED} 其中一个.
         * @param errString 错误提示信息
         */
        @Override
        public void onAuthenticationError(int errMsgId, CharSequence errString) {
            super.onAuthenticationError(errMsgId, errString);
            switch (errMsgId) {
                case FingerprintManager.FINGERPRINT_ERROR_CANCELED://取消验证
                    tv_show.setText("取消指纹验证:" + errMsgId + " , " + errString);
                    break;
                case FingerprintManager.FINGERPRINT_ERROR_LOCKOUT://多次验证失败
                    tv_show.setText("多次验证失败:" + errMsgId + " , " + errString);
                    break;
                default:

                    break;
            }
        }

        /**
         * 在验证过程中,遇到可恢复的异常时该方法被调用.(传感器脏，请把它擦干净。...)
         *
         * @param helpMsgId
         * @param helpString 提示信息
         */
        @Override
        public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
            super.onAuthenticationHelp(helpMsgId, helpString);
            tv_show.setText("指纹模块异常:" + helpMsgId + " , " + helpString);
        }

        /**
         * 指纹验证成功
         *
         * @param result
         */
        @Override
        public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
            super.onAuthenticationSucceeded(result);
            tv_show.setText("指纹验证成功!");
            tv_show.setTextColor(Color.GREEN);
        }

        /**
         * 指纹验证失败
         */
        @Override
        public void onAuthenticationFailed() {
            super.onAuthenticationFailed();
            tv_show.setText("指纹验证失败!");
            tv_show.setTextColor(Color.RED);
        }
    }
}
